package com.example.springboottestgit.service;

import com.alibaba.fastjson.JSONObject;
import com.example.springboottestgit.bean.*;
import com.example.springboottestgit.bean.vo.*;
import com.example.springboottestgit.dao.*;
import com.example.springboottestgit.enums.SeparatorEnum;
import com.example.springboottestgit.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @description:投标文件-技术要求
 * @author: ZZZ
 */
@Slf4j
@Service
public class SubmitTenderService {

    @Autowired
    private TenderQuestionTemplateMapper tenderQuestionTemplateMapper;
    @Autowired
    private SubmitTenderContentQaRecordMapper submitTenderContentQaRecordMapper;
    @Autowired
    private InviteTenderContentQaRecordMapper inviteTenderContentQaRecordMapper;
    @Autowired
    private SubmitTenderFileUploadRecordMapper submitTenderFileUploadRecordMapper;
    @Autowired
    private InviteTenderFileUploadRecordMapper inviteTenderFileUploadRecordMapper;
    @Autowired
    private TenderBsnMapper tenderBsnMapper;

    @Autowired
    private ModelServer modelServer;

    @Autowired
    private ExeScriptServer exe;

    @Value("${tender.technology.query.url}")
    private String tenderTechnologyQueryUrl;

    @Value("${tender.question.switch}")
    private Boolean tenderQuestionSwitch;

    @Value("${tender.technology.switch}")
    private Boolean tenderTechnologySwitch;


    @Value("${tender.analysis.path}")
    private String tenderAnalysisPath;

    @Value("${es.delay.query}")
    private Integer delayQuery;


    @Autowired
    private ElasticSearchClientServer es;


    @Scheduled(cron = "0/30 * * * * ? ")
    public void inviteTask() {
        //status 0-待解析 1-完成 2-失败 3-解析完成
        //1-等解析完成后，开始模型审核
        List<String> list = tenderBsnMapper.queryBsnList(0);
        for (String bsn : list) {
            int unAnalysis = inviteTenderFileUploadRecordMapper.exeCount(bsn, 0) + submitTenderFileUploadRecordMapper.exeCount(bsn, 0);
            int analysis = inviteTenderFileUploadRecordMapper.exeCount(bsn, 1) + submitTenderFileUploadRecordMapper.exeCount(bsn, 1);
            if (unAnalysis == 0 && analysis > 0) {
                //解析完成更新状态
                tenderBsnMapper.updateBsnStatusAndTime(bsn, 3);
                log.info("======{} 开始大模型审核=====", bsn);
                //开始大模型审核
                tenderContentQa2(bsn);
            }
        }
        //2-解析完成后 看模型是否审核完成
        List<String> list2 = tenderBsnMapper.queryBsnList(3);
        for (String bsn : list2) {
            //检查项类型：1-负面清单；2-基础检查；3-证明材料；4-技术要求; 5-法律法规
            //1-负面清单;4-技术要求;5-法律法规   invite_tender_content_qa_record
            //2-基础检查；3-证明材料； submit_tender_content_qa_record
            int n = inviteTenderContentQaRecordMapper.inviteTenderExeCount(bsn, 0) + submitTenderContentQaRecordMapper.submitTenderExeCount(bsn, 0);
            int y = inviteTenderContentQaRecordMapper.inviteTenderExeCount(bsn, 1) + submitTenderContentQaRecordMapper.submitTenderExeCount(bsn, 1);
            //log.info(bsn + " 未执行:" + n + " 已执行:" + y);
            if (n == 0 && y > 0) {
                tenderBsnMapper.updateBsnStatusAndTime(bsn, 1);
                Long exeTime = tenderBsnMapper.queryBsn(bsn).getExeTime();
                log.info("======{} 更新状态成功 耗时 {} 秒=====", bsn, exeTime);
            }
        }
    }


    @Scheduled(cron = "0 0/2 * * * ? ")
    public void un_exe() {
        List<Long> invite = inviteTenderContentQaRecordMapper.unExe(10);
        for (Long id : invite) {
            InviteTenderContentQaRecord update = new InviteTenderContentQaRecord();
            update.setId(id);
            update.setExeStatus(2);
            update.setStatus(2);
            inviteTenderContentQaRecordMapper.updateById(update);

        }

        List<Long> submit = submitTenderContentQaRecordMapper.unExe(10);
        for (Long id : submit) {
            SubmitTenderContentQaRecord update = new SubmitTenderContentQaRecord();
            update.setId(id);
            update.setExeStatus(2);
            update.setStatus(2);
            submitTenderContentQaRecordMapper.updateById(update);
        }

    }


    @Async("myAsync")
    public void tenderContentQa(String bsn) {

        TenderBsn tenderBsn = tenderBsnMapper.queryBsn(bsn);
        if (tenderBsn.getStatus() != 0) {
            log.info("=========招投标文件 已经解析过了===========");
            return;
        }
        //tenderBsnMapper.updateBsnStatus(bsn, 3);

        String inviteTenderTxtPath = tenderAnalysisPath + bsn + "/招标" + "/商务文件-拆分后.txt";
        String submitTenderTxtPath = tenderAnalysisPath + bsn + "/投标" + "/商务文件-拆分后.txt";

        String inviteTechnologyTxtPath = tenderAnalysisPath + bsn + "/招标" + "/技术文件-拆分后.txt";
        String submitTechnologyTxtPath = tenderAnalysisPath + bsn + "/投标" + "/技术文件-拆分后.txt";


        List<InviteTenderFileUploadRecord> inviteTenderFileList = inviteTenderFileUploadRecordMapper.queryInviteTenderFileList(bsn);
        for (InviteTenderFileUploadRecord inviteTenderFileUploadRecord : inviteTenderFileList) {
            // 0：单个文件  1：商务文件 2：技术文件 3：价格文件
            Integer fileType = inviteTenderFileUploadRecord.getFileType();
            long id = inviteTenderFileUploadRecord.getId();
            exe.exeScript(id, inviteTenderFileUploadRecord.getFilePath(), inviteTenderFileUploadRecord.getBsn() + "-招标-" + fileType, inviteTenderFileUploadRecord.getFileType(), 0, inviteTenderTxtPath, inviteTechnologyTxtPath);
        }

        List<SubmitTenderFileUploadRecord> submitTenderFileList = submitTenderFileUploadRecordMapper.querySubmitTenderFileList(bsn);
        for (SubmitTenderFileUploadRecord submitTenderFileUploadRecord : submitTenderFileList) {
            // 0：单个文件  1：商务文件 2：技术文件 3：价格文件
            long id = submitTenderFileUploadRecord.getId();
            Integer fileType = submitTenderFileUploadRecord.getFileType();
            exe.exeScript(id, submitTenderFileUploadRecord.getFilePath(), submitTenderFileUploadRecord.getBsn() + "-投标-" + fileType, submitTenderFileUploadRecord.getFileType(), 1, submitTenderTxtPath, submitTechnologyTxtPath);

        }
    }


    public void tenderContentQa2(String bsn) {
        try {

            String inviteTenderTxtPath = tenderAnalysisPath + bsn + "/招标" + "/商务文件-拆分后.txt";
            String submitTenderTxtPath = tenderAnalysisPath + bsn + "/投标" + "/商务文件-拆分后.txt";

            String inviteTechnologyTxtPath = tenderAnalysisPath + bsn + "/招标" + "/技术文件-拆分后.txt";
            String submitTechnologyTxtPath = tenderAnalysisPath + bsn + "/投标" + "/技术文件-拆分后.txt";


            String inviteTenderIndexId = "z-" + bsn;
            String submitTenderIndexId = "t-" + bsn;
            log.info("=========招标商务文件 ES 入库===========");
            es.createIndexContent(inviteTenderIndexId, inviteTenderTxtPath, "\\$\\$\\$\\$\\$");
            log.info("=========投标商务文件 ES 入库===========");
            es.createIndexContent(submitTenderIndexId, submitTenderTxtPath, "\\$\\$\\$\\$\\$");
            Thread.sleep(delayQuery);

            LocalDateTime middleTime1 = LocalDateTime.now();
            //1-问题模版检索内容
            if (tenderQuestionSwitch) {

                //法律法规审查
                String textContent = textContent(inviteTenderTxtPath).replace("#####", "$$$$$").replace("*****", "$$$$$").replace("&&&&&", "$$$$$");
                String[] split = textContent.split("\\$\\$\\$\\$\\$");
                for (String inviteTenderContent : split) {

                    int textLength = inviteTenderContent.trim().length();

                    if (textLength > 500 || textLength < 50) {
                        continue;
                    }
                    modelServer.lawCheck(inviteTenderContent, bsn);
                }

                List<TenderQuestionVO> list = tenderQuestionTemplateMapper.queryQuestion();
                //submitTenderFileUploadRecord.setMateTotalNum(list.size());
                //submitTenderFileUploadRecordMapper.updateById(submitTenderFileUploadRecord);
                //String indexId = UUID.randomUUID().toString().replace("-", "");

                for (TenderQuestionVO tenderQuestionVO : list) {
                    long questionId = tenderQuestionVO.getQuestionId();
                    Integer questionType = tenderQuestionVO.getQuestionType();

                    String inviteSearchContent = tenderQuestionVO.getInviteSearchContent();
                    String submitSearchContent = tenderQuestionVO.getSubmitSearchContent();

                    SubmitTenderContentQaRecord insert = new SubmitTenderContentQaRecord();
                    //insert.setInviteTenderFileId(inviteTenderFileId);
                    //insert.setSubmitTenderFileId(id);
                    insert.setBsn(bsn);
                    insert.setQuestionType(questionType);
                    insert.setQuestionId(questionId);
                    insert.setInspectItem(tenderQuestionVO.getInspectItem());
                    insert.setInspectItemType(tenderQuestionVO.getInspectItemType());
                    insert.setInviteQuestionName(tenderQuestionVO.getInviteQuestionName());
                    insert.setSubmitQuestionName(tenderQuestionVO.getSubmitQuestionName());
                    modelServer.submitTenderContentQa(insert, inviteSearchContent, submitSearchContent, inviteTenderTxtPath, submitTenderTxtPath, inviteTenderIndexId, submitTenderIndexId);
                }
                LocalDateTime middleTime2 = LocalDateTime.now();
                Duration between1 = Duration.between(middleTime1, middleTime2);
                //log.info("招投标问题检索问答:  耗时 {} 秒", between1.getSeconds());
            }

            //2-技术要求相识度匹配
            if (tenderTechnologySwitch) {
                log.info("=========开始技术要求对比===========");
                LocalDateTime technologyStartTime = LocalDateTime.now();

                String originInviteText = textContent(inviteTechnologyTxtPath);
                String originSubmitText = textContent(submitTechnologyTxtPath);
                // 以招标技术为主先按照层级拆分
                log.info("=========招标技术分层===========");
                List<TechnologyVO> firstList = new ArrayList<>();
                List<TechnologyVO> secondList = new ArrayList<>();
                List<TechnologyVO> thirdList = new ArrayList<>();
                List<TechnologyVO> inviteList = new ArrayList<>();
                inviteTenderSeparator(bsn, originInviteText, originSubmitText, "#####", firstList, secondList, thirdList, inviteList);
                tenderSeparatorResultSave(inviteTechnologyTxtPath, firstList, "技术要求拆分第一层");
                tenderSeparatorResultSave(inviteTechnologyTxtPath, secondList, "技术要求拆分第二层");
                tenderSeparatorResultSave(inviteTechnologyTxtPath, thirdList, "技术要求拆分第三层");
                tenderSeparatorResultSave(inviteTechnologyTxtPath, inviteList, "技术要求拆分所有");

                LocalDateTime technologyMiddleTime = LocalDateTime.now();
                Duration between1 = Duration.between(technologyStartTime, technologyMiddleTime);
                log.info("招标技术要求 分层 :  耗时  {}  秒", between1.getSeconds());

                // 以投标文件继续拆分
                log.info("=========投标技术分成===========");
                List<TechnologyVO> submitList = new ArrayList<>();
                for (TechnologyVO technologyVO : inviteList) {
                    String inviteTender = technologyVO.getInviteTender();
                    String submitTender = technologyVO.getSubmitTender();
                    // 避免只有$$$$$的情况
                    if (submitTender.contains("*****")) {
                        submitTenderSeparator(bsn, inviteTender, submitTender, "*****", submitList);
                    } else if (submitTender.contains("$$$$$")) {
                        submitTenderSeparator(bsn, inviteTender, submitTender, "$$$$$", submitList);
                    } else {
                        technology(bsn, inviteTender, submitTender, submitList);
                    }
                }

                tenderSeparatorResultSave(submitTechnologyTxtPath, submitList, "技术要求拆分所有");

                LocalDateTime technologyEndTime = LocalDateTime.now();
                Duration between2 = Duration.between(technologyStartTime, technologyEndTime);
                log.info("招投标技术要求 分层 :  总耗时  {}  秒", between2.getSeconds());
            }
            //LocalDateTime endTime = LocalDateTime.now();
            //Duration between2 = Duration.between(startTime, endTime);

            //3-更新投标文件状态
            //updateSubmitTenderStatus(id, between2.getSeconds());
            //submitTenderFileUploadRecordMapper.updateSubmitTenderFileStatus(bsn, 1);
            //tenderBsnMapper.updateBsnStatusAndTime(bsn, between2.getSeconds(), 1);
            //log.info("招投标文件执行:  总耗时 {} 秒", between2.getSeconds());

        } catch (Exception e) {
            tenderBsnMapper.updateBsnStatus(bsn, 2);
            log.error("招投标文件解析失败", e);
            throw new BusinessException("001001", "招投标文件解析失败");
        }
    }

    public void analysisResultSave(Integer fileType, String businessTxtPath, String technologyTxtPath, OutputVO outputVO) {

        if (fileType == 0) {
            FileUtil.txtWriterAppend(businessTxtPath, outputVO.getData().getBusinessContent());
            FileUtil.txtWriterAppend(technologyTxtPath, outputVO.getData().getTechnologyContent());
        }

        if (fileType == 1 || fileType == 3) {
            //businessContent  空取 initContent
            if (!StringUtils.hasText(outputVO.getData().getBusinessContent())) {
                outputVO.getData().setBusinessContent(outputVO.getData().getInitContent());
            }
            FileUtil.txtWriterAppend(businessTxtPath, outputVO.getData().getBusinessContent());
        }

        if (fileType == 2) {
            //technologyContent 空取 initContent
            if (!StringUtils.hasText(outputVO.getData().getTechnologyContent())) {
                outputVO.getData().setTechnologyContent(outputVO.getData().getInitContent());
            }
            FileUtil.txtWriterAppend(technologyTxtPath, outputVO.getData().getTechnologyContent());
        }
    }

    //以招标文件为主拆分 递归写法
    public void inviteTenderSeparator(String bsn, String inviteContent, String submitContent, String separator, List<TechnologyVO> firstList, List<TechnologyVO> secondList, List<TechnologyVO> thirdList, List<TechnologyVO> finalList) throws Exception {
        //if (separatorMap.containsKey(separator)) {
        SeparatorEnum separatorEnum = SeparatorEnum.getSeparatorEnum(separator);
        String nowSplit = separatorEnum.getNowSplit();

        String submitTechnologyIndexId = "tjs-" + UUID.randomUUID().toString().replace("-", "");
        addContentByIndexId(submitTechnologyIndexId, nowSplit, submitContent);
        String inviteTender[] = inviteContent.split(nowSplit);
        for (String inviteText : inviteTender) {
            if (inviteText.trim().length() > 5) {
                String submitText = es.queryOneContent(submitTechnologyIndexId, inviteText);
                //记录第一层级
                if ("#####".contains(separator)) {
                    addList(inviteText, submitText, firstList);
                }
                //记录第二层级
                if ("*****".contains(separator)) {
                    addList(inviteText, submitText, secondList);
                }
                //记录第三层级
                if ("$$$$$".contains(separator)) {
                    addList(inviteText, submitText, thirdList);
                }

                //下一次分隔符
                String nexSeparator = separatorEnum.getNexSeparator();
                //是否继续分割 有分隔符就继续分割
                if (StringUtils.hasText(nexSeparator) && inviteText.contains(nexSeparator)) {
                    inviteTenderSeparator(bsn, inviteText, submitText, nexSeparator, firstList, secondList, thirdList, finalList);
                } else {
                    //technology(bsn, inviteText, submitText, finalList);
                    TechnologyVO vo = new TechnologyVO();
                    vo.setInviteTender(inviteText);
                    vo.setSubmitTender(submitText);
                    finalList.add(vo);
                }
            }
        }
        //}
    }

    public void submitTenderSeparator(String bsn, String inviteContent, String submitContent, String separator, List<TechnologyVO> finalList) throws Exception {

        SeparatorEnum separatorEnum = SeparatorEnum.getSeparatorEnum(separator);
        String nowSplit = separatorEnum.getNowSplit();

        String submitTechnologyIndexId = "tjs-" + UUID.randomUUID().toString().replace("-", "");
        addContentByIndexId(submitTechnologyIndexId, nowSplit, submitContent);
        String submitText = es.queryOneContent(submitTechnologyIndexId, inviteContent);

        //下一次分隔符
        String nexSeparator = separatorEnum.getNexSeparator();
        //是否继续分割 有分隔符就继续分割
        if (StringUtils.hasText(nexSeparator) && submitText.contains(nexSeparator)) {
            submitTenderSeparator(bsn, inviteContent, submitText, nexSeparator, finalList);
        } else {
            technology(bsn, inviteContent, submitText, finalList);
        }

    }

    public void tenderSeparatorResultSave(String path, List<TechnologyVO> list, String newFileName) {
        //log.info(JSONObject.toJSONString(list));
        modelServer.txtWriter(path, JSONObject.toJSONString(list), newFileName);
    }

    public void addContentByIndexId(String indexId, String regex, String submitText) throws Exception {
        es.createIndex(indexId);
        String submitTextList[] = submitText.split(regex);
        for (String text : submitTextList) {
            es.addContentByIndexId(indexId, text);
        }
        Thread.sleep(delayQuery);
    }

    public void addList(String inviteText, String submitText, List<TechnologyVO> list) throws Exception {
        TechnologyVO vo = new TechnologyVO();
        vo.setInviteTender(inviteText);
        vo.setSubmitTender(submitText);
        list.add(vo);
    }


    public void technology(String bsn, String inviteTechnology, String submitTechnology, List<TechnologyVO> list) {
        TechnologyVO vo = new TechnologyVO();
        //技术长度限制
        inviteTechnology = inviteTechnology.length() > 10000 ? inviteTechnology.substring(0, 10000) : inviteTechnology;
        submitTechnology = submitTechnology.length() > 10000 ? submitTechnology.substring(0, 10000) : submitTechnology;
        vo.setInviteTender(inviteTechnology);
        vo.setSubmitTender(submitTechnology);
        list.add(vo);
        InviteTenderContentQaRecord insert = new InviteTenderContentQaRecord();
        insert.setBsn(bsn);
        //insert.setQuestionType(8);
        insert.setInspectItem("技术要求");
        insert.setInspectItemType(4);
        insert.setResult(inviteTechnology);
        insert.setSubmitTenderResult(submitTechnology);
        inviteTenderContentQaRecordMapper.insert(insert);
        modelServer.tenderFamiliarityMate(insert, inviteTechnology, submitTechnology);
    }


    public TenderAnalysisResultVO submitTenderDetailQuery(String bsn, String keywords, Integer inspectItemType, String status) {
        TenderAnalysisResultVO vo = new TenderAnalysisResultVO();
        TenderBsn tenderBsn = tenderBsnMapper.queryBsn(bsn);
        vo.setStatus(tenderBsn.getStatus());
        if (vo.getStatus() == 1 || vo.getStatus() == 3) {
            //检查列表（总）
            List<TenderInspectVO> list = new ArrayList<>();
            //检查项类型：1-负面清单；2-基础检查；3-证明材料；4-技术要求; 5-法律法规
            //1-负面清单;4-技术要求;5-法律法规   invite_tender_content_qa_record
            list.addAll(inviteTenderContentQaRecordMapper.inviteTenderInspectList(bsn, keywords, inspectItemType, status));
            //2-基础检查；3-证明材料； submit_tender_content_qa_record
            list.addAll(submitTenderContentQaRecordMapper.submitTenderInspectList(bsn, keywords, inspectItemType, status));
            //技术要求 invite_tender_content_qa_record
            //list.addAll(inviteTenderContentQaRecordMapper.inviteTenderInspectList(bsn, 8));

            //检查匹配成功列表
            List<TenderInspectVO> inspectMateSuccessList = new ArrayList<>();
            //检查匹配失败列表
            List<TenderInspectVO> inspectMateFailList = new ArrayList<>();

            for (TenderInspectVO tenderInspectVO : list) {

                if ("符合".equals(tenderInspectVO.getMateMark())) {
                    inspectMateSuccessList.add(tenderInspectVO);
                } else {
                    inspectMateFailList.add(tenderInspectVO);
                }
            }
            vo.setInspectList(list);
            vo.setMateTotalNum(list.size());

            vo.setInspectMateSuccessList(inspectMateSuccessList);
            vo.setMateSuccessNum(inspectMateSuccessList.size());

            vo.setInspectMateFailList(inspectMateFailList);
            vo.setMateFailNum(inspectMateFailList.size());

        }
        return vo;
    }

    public TenderViewDetailVO submitTenderViewDetail(String bsn) {
        TenderViewDetailVO vo = new TenderViewDetailVO();
        String submitTenderFilePath = submitTenderFileUploadRecordMapper.queryFilePath(bsn);
        vo.setSubmitTenderFilePath(submitTenderFilePath);

        String inviteTenderFilePath = inviteTenderFileUploadRecordMapper.queryFilePath(bsn);
        vo.setInviteTenderFilePath(inviteTenderFilePath);

        List<TenderFileContentVO> list = inviteTenderFileUploadRecordMapper.inviteTenderTechnologyList(bsn);
        vo.setList(list);
        return vo;
    }

    public String contentFilter(String content) {
        content = content.replace("根据提供的知识文本，", "").replace("根据提供的知识文本,", "");
        return content;
    }


    public List<SubmitTenderFileVO> submitTenderFileList(long inviteTenderFileId) {
        List<SubmitTenderFileVO> list = submitTenderFileUploadRecordMapper.submitTenderFileList(inviteTenderFileId);
        return list;
    }

    public void txtWriter(String filePath, String fileContent, String newFileName) {
        File file = new File(filePath);
        String fileName = file.getName();
        newFileName = newFileName + "-" + fileContent.length() + ".txt";
        filePath = filePath.replace(fileName, newFileName);

        FileUtil.txtWriter(filePath, fileContent);

    }

    public String textContent(String filePath) throws IOException {
        FileReader reader = new FileReader(filePath);
        BufferedReader bufferedReader = new BufferedReader(reader);
        StringBuilder stringBuilder = new StringBuilder();
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            stringBuilder.append(line).append("\n");
        }
        bufferedReader.close();
        return stringBuilder.toString();
    }


}
